﻿
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public class DL645Protocol
{
    // 协议常量
    private const byte FRAME_START = 0x68;
    private const byte FRAME_END = 0x16;
    private const byte ESCAPE_CHAR = 0xFE;

    // 构建请求帧
    public byte[] BuildRequestFrame(string meterAddress, byte ctrlCode, byte[] data)
    {
        List<byte> frame = new List<byte>();

        // 帧起始符
        frame.Add(FRAME_START);

        // 地址域 (6字节BCD码，低位在前)
        byte[] addrBytes = ParseAddress(meterAddress);
        frame.AddRange(addrBytes);
        frame.Add(FRAME_START);

        // 控制码
        frame.Add(ctrlCode);

        // 数据域长度
        frame.Add((byte)data.Length);

        // 数据域 (含转义处理)
        frame.AddRange(EscapeData(data));

        // 校验和
        byte cs = CalculateChecksum(frame.ToArray(), 1, frame.Count - 1);
        frame.Add(cs);

        // 结束符
        frame.Add(FRAME_END);

        return frame.ToArray();
    }

    // 解析响应帧
    public DL645Frame ParseResponseFrame(byte[] rawData)
    {
        if (rawData == null || rawData.Length < 12)
            throw new ArgumentException("帧长度不足");

        // 验证帧头帧尾
        if (rawData[0] != FRAME_START || rawData[7] != FRAME_START)
            throw new ArgumentException("帧格式错误");

        // 校验和验证
        byte calcCs = CalculateChecksum(rawData, 1, rawData.Length - 3);
        if (calcCs != rawData[rawData.Length - 2])
            throw new ArgumentException("校验和错误");

        // 解析地址
        string address = ParseAddressToString(rawData, 1, 6);

        // 控制码
        byte controlCode = rawData[8];

        // 数据域长度
        int dataLen = rawData[9];

        // 数据域 (反转义处理)
        byte[] data = UnescapeData(rawData, 10, dataLen);

        return new DL645Frame(address, controlCode, data);
    }

    private byte[] UnescapeData(byte[] rawData, int v, int dataLen)
    {
        return null;
    }

    private string ParseAddressToString(byte[] rawData, int v1, int v2)
    {
        return null;
    }

    // 地址转换 (BCD编码)
    private byte[] ParseAddress(string address)
    {
        byte[] bytes = new byte[6];
        for (int i = 0; i < 6; i++)
        {
            if (i * 2 < address.Length)
            {
                string hex = address.Substring(i * 2, Math.Min(2, address.Length - i * 2));
                bytes[i] = Convert.ToByte(hex.PadLeft(2, '0'), 16);
            }
            else
            {
                bytes[i] = 0x00;
            }
        }
        return bytes;
    }

    // 数据转义处理
    private byte[] EscapeData(byte[] data)
    {
        List<byte> result = new List<byte>();
        foreach (byte b in data)
        {
            if (b == FRAME_START || b == FRAME_END || b == ESCAPE_CHAR)
            {
                result.Add(ESCAPE_CHAR);
                result.Add((byte)(b ^ 0x80));
            }
            else
            {
                result.Add(b);
            }
        }
        return result.ToArray();
    }

    // 校验和计算
    private byte CalculateChecksum(byte[] data, int start, int length)
    {
        byte sum = 0;
        for (int i = start; i < start + length; i++)
        {
            sum += data[i];
        }
        return sum;
    }
}

public class DL645Frame
{
    public string Address { get; }
    public byte ControlCode { get; }
    public byte[] Data { get; }

    public DL645Frame(string address, byte controlCode, byte[] data)
    {
        Address = address;
        ControlCode = controlCode;
        Data = data;
    }
}
